/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package lineage.core.handler;

import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;

import lineage.core.L1GameClient;
import lineage.core.thread.pool.L1ThreadPool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 封包输出处理程序.
 * 将'写处理器'送来的封包加入队列,轮询发送至客户端.
 * 
 * @version 2014年3月10日下午2:26:02
 * @author jrwz
 */
public final class L1PacketSendHandler extends L1AbstractHandler implements Runnable {
    private static final Logger LOG = LoggerFactory.getLogger(L1PacketSendHandler.class);
    private final L1WriteHandler write;

    public L1PacketSendHandler(final L1GameClient client, L1WriteHandler write) {
        this.client = client;
        keys = this.client.getKeys();
        this.write = write;
        queue = new ConcurrentLinkedQueue<byte[]>(); // 创建一个最初为空的 ConcurrentLinkedQueue
        L1ThreadPool.getInstance().schedule(this, 0); // 运行线程
    }

    @Override
    public void run() {
        try {
            while (client.getSocket() != null) {
                for (final Iterator<byte[]> iter = queue.iterator(); iter.hasNext();) {
                    final byte[] data = iter.next(); // 取得元素
                    iter.remove(); // 删除元素
                    execute(data); // 发送
                    Thread.sleep(1);
                }
                Thread.sleep(10);
            }
        } catch (final Exception e) {
            LOG.error(e.getLocalizedMessage(), e);
        } finally {
            close();
        }
    }

    // 向客户端发送封包
    @Override
    protected void execute(final byte[] data) {
        synchronized (write) {
            try {
                final byte[] ed = write.toEncrypt(data); // 加密

                if (write.getOut() != null && ed != null) {
                    final int length = ed.length + 2;
                    write.getOut().write(length & 0xff);
                    write.getOut().write(length >> 8 & 0xff);
                    write.getOut().write(ed);
                    write.getOut().flush();
                }
            } catch (final IOException e) {
                write.close();
                // TODO
            } catch (final Exception e) {
                // TODO
            }
        }
    }

    @Override
    public void executeQueue(final byte[] data) {
        queue.offer(data);
    }

    @Override
    public void close() {
        queue.clear(); // 移除此 collection 中的所有元素
    }
}
